const { series, parallel, src, dest, watch } = require("gulp");
const babel = require("gulp-babel"); // 支持es6以及模块化
const uglify = require("gulp-uglify"); // 压缩js代码
const rename = require("gulp-rename"); // 重命名文件
const clean = require("gulp-clean"); // 清空文件夹
const csso = require("gulp-csso"); // 压缩css
const htmlmin = require("gulp-htmlmin"); // 压缩html
const gulpServer = require("gulp-webserver"); // 启动项目
const htmlreplace = require("gulp-html-replace"); // 替换文件引用地址
const replace = require("gulp-string-replace"); // 替换字符串
const browserSync = require("browser-sync"); // 启动项目
const reload = browserSync.reload; // 更新页面

// 配置压缩html的规则
const indexOptions = {
  removeComments: true, // 清除html注释
  collapseWhitespace: true, // 压缩html
  collapseBooleanAttributes: true, //省略布尔属性的值 <input checked="true"/> -> <input checked />
  removeEmptyAttributes: true, // 删除所有空格作为属性值 <inpit id=""/> -> <inpit/>
  minifyCss: true, // 压缩页面中的css
  minifyJs: true, // 压缩页面中的js
};

// 清空dist文件夹
function cleans() {
  // 获取到dist文件夹下面的所有文件，进行清空操作
  return src(["./dist/*"]).pipe(clean());
}

// 压缩js
function js() {
  // 即使这个任务不需要回调，但也要有一个默认的回调方法,也可以return
  // cb();
  return src("src/public/js/*.js")
    .pipe(babel())
    .pipe(uglify()) // 压缩js代码
    .pipe(replace(/assetApi/g, "https://www.gulpjs.com.cn")) // 替换代码中的 "assetApi"
    .pipe(rename({ extname: ".min.js" })) // 将匹配到的文件重名名为xxx.main.js
    .pipe(dest("dist/js/")); // 将文件写入到 dist/js/ 目录下
}

// 压缩打包html
function html() {
  return src(["src/view/**/*.html"])
    .pipe(htmlmin(indexOptions)) // 使用上面定义的压缩配置进行压缩html
    .pipe(dest("dist/html/")); // 将文件写入到 dist/html/ 目录下
}

// 单独处理一下 index.html
function indexhtml() {
  return src("src/index.html")
    .pipe(
      htmlreplace({
        // 从注释标记中获取要替换的路径
        css: "css/index.css",
        js: "js/index.min.js",
      })
    )
    .pipe(htmlmin(indexOptions)) // 使用上面定义的压缩配置进行压缩html
    .pipe(dest("dist/"));
}

// 压缩css
function css() {
  return src("src/public/css/**/*.css").pipe(csso()).pipe(dest("dist/css"));
}

// 启动项目
function server() {
  browserSync({
    notify: false, // 关闭通知，页面右上角不会出现弹框
    port: 3000, // 启动 3000 端口
    server: {
      baseDir: ["src"], // 配置根目录，在这个根目录下启动服务器
    },
    callbacks: {
      // 项目启动成功后执行的方法
      ready: () => {
        console.log("开始监控开发文件夹");
        // 设置要监控的页面，当被监控页面发生变化时执行重载方法
        const watcher = watch(["src/**/*.html", "src/**/*.js", "src/**/*.css"]);
        // 监听到变化后执行
        watcher.on("change", () => {
          // 页面变化后执行重载方法
          reload();
        });
      },
    },
  });
}

/**
 * 打包任务
 * 私有任务也可以在 series 组合中使用
 * series 是顺序执行多个任务
 * parallel 是平行执行多个任务
 */
const build = series(cleans, js, html, indexhtml, css, function (cb) {
  // 必须要有一个回调方法
  cb();
});

// 公开 server 任务，执行 gulp server 运行启动任务
exports.server = server;
// 公开 build 任务，执行 gulp build 运行打包任务
exports.build = build;
